package class04;

/** hard
 * @description: https://leetcode.com/problems/reverse-nodes-in-k-group/
 * K个节点的组内逆序调整：
 *    给定一个单链表的头节点head，和一个正数k
 *    实现k个节点的小组内部逆序，如果最后一组不够k个就不调整
 * 例子:
 * 调整前：1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8，k = 3
 * 调整后：3 -> 2 -> 1 -> 6 -> 5 -> 4 -> 7 -> 8
 * @time: 2021/7/17 22:00
 * @author: lhy
 */
public class ReverseNodesInKGroup {

    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode start = head;
        ListNode end = getKGroupEnd(start,k);
        if (end == null) {
            return head;
        }
        head = end;
        reverse(start,end);
        ListNode lastEnd = start;
        while (lastEnd.next != null){
            start = lastEnd.next;
            end = getKGroupEnd(start,k);
            if (end == null) {
                return head;
            }
            reverse(start,end);
            lastEnd.next = end;
            lastEnd = start;
        }
        return head;
    }

    /**
     * 根据 k 划分一组，返回该组的最后一个节点
     * @param start 开始的节点
     * @param k 划分的个数
     * @return 如果不够 k 个，返回 null
     */
    private ListNode getKGroupEnd(ListNode start, int k){
        while (--k != 0 && start != null){
            start = start.next;
        }
        return start;
    }

    /**
     * 完成 start...end 之间的逆序
     * @param start
     * @param end
     */
    private void reverse(ListNode start, ListNode end){
        end = end.next;
        ListNode pre = null;
        ListNode cur = start;
        ListNode next = null;
        while (cur != end){
            next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        start.next = end;
    }
}
